package middleware.p2p.transaction;

import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Transaction {
	private class TransactionPartecipantInfo {
		public boolean canCommit;		
		public boolean committed;
		public TransactionPartecipantInfo() {
			this.canCommit=false;
			this.committed=false;
		}
	}
	private String id;
	private Map<URL,TransactionPartecipantInfo> partecipants;
	private TransactionState state;
	public Transaction(String id) {
		this.id=id;
		this.partecipants=new HashMap<URL, TransactionPartecipantInfo>();
		this.setState(TransactionState.Started);
	}
	public synchronized String getId() {
		return this.id;
	}
	public synchronized boolean isCompleted() {
		return (this.state==TransactionState.Completed);
	}
	public synchronized void flagAsCompleted() {
		this.state=TransactionState.Completed;
	}
	public synchronized boolean registerJoin(URL rmWsdl) {
		if (!this.partecipants.containsKey(rmWsdl)) {
			this.partecipants.put(rmWsdl, null);
			return true;
		} else {
			return false;
		}		
	}
	public synchronized boolean registerCommitVote(URL rmWsdl,boolean vote) {
		if (this.partecipants.containsKey(rmWsdl)) {
			this.partecipants.put(rmWsdl, new TransactionPartecipantInfo());
			this.partecipants.get(rmWsdl).canCommit=vote;
			return true;
		} else {
			return false;
		}
	}
	public synchronized boolean registerCommit(URL rmWsdl) {
		if (this.partecipants.containsKey(rmWsdl)) {
			this.partecipants.get(rmWsdl).committed=true;
			return true;
		} else {
			return false;
		}
	}	
	public synchronized URL[] getPartecipants() {
		Set<URL> keys=this.partecipants.keySet();
		URL retArr[]=new URL[keys.size()];
		keys.toArray(retArr);
		return retArr;		
	}
	public synchronized boolean checkVotes() {
		Set<URL> keys=this.partecipants.keySet();
		Iterator<URL> it=keys.iterator();
		if (this.state==TransactionState.GlobalAbort) return false;
		while (it.hasNext()) {
			URL currRM=it.next();
			TransactionPartecipantInfo info=this.partecipants.get(currRM);
			if (!info.canCommit) return false;
		}
		return true;
	}
	public synchronized boolean checkCompleted() {
		Set<URL> keys=this.partecipants.keySet();
		Iterator<URL> it=keys.iterator();
		while (it.hasNext()) {
			URL currRM=it.next();
			TransactionPartecipantInfo info=this.partecipants.get(currRM);
			if (!info.committed) return false;
		}
		return true;
	}
	public synchronized void setAborted() {
		this.state=TransactionState.GlobalAbort;
	}
	public synchronized boolean isAborted() {
		return (this.state==TransactionState.GlobalAbort);
	}
	public synchronized void setState(TransactionState state) {
		this.state = state;
	}
	public synchronized TransactionState getState() {
		return state;
	}
}
